/*
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * RSNodeBase.h
 *
 *  Created on: 2010/03/03
 *      Author: Alexandre Pires ( c.alexandre.pires@gmail.com )
 */

#ifndef RSNODEBASE_H_
#define RSNODEBASE_H_

#include "RSUIDElement.h"
#include <QMatrix4x4>

namespace Realsphere {

    class RSNodeBase: public Realsphere::RSUIDElement {
        Q_OBJECT
        Q_PROPERTY ( QString _attr_name READ Name WRITE SetName )
        Q_PROPERTY ( QString _attr_sid READ ScopeId WRITE SetScopeId )
        public:
            RSNodeBase ( RSNodeType rNodeType,
                         const QString& rId = QString::null,
                         const QString& rName = QString::null,
                         const QString& rScopeId = QString::null);
            virtual ~RSNodeBase() = 0;

        public:
            QString                     ScopeId () const;
            RSTransformationElement*    GetTransformation ( const QString& rScopeId ) const;
            RSTransformationElement*    GetTransformation ( unsigned int rIndex ) const;
            int                         IndexOf ( RSTransformationElement* rTransformationElement );
            unsigned int                TransformationsSize ();
            RSTransformations           Transformations () const;
            RSTransformations           Transformations ( RSTransformationType rTransformationType ) const;
            RSTransformationsIterator   TransformationsIterator () const;
            RSTransformationsIterator   TransformationsIterator ( RSTransformationType rTransformationType ) const;
            RSNodeBase*                 GetChildNode ( const QString& rId ) const;
            RSNodeBase*                 GetChildNode ( unsigned int rIndex ) const;
            int                         IndexOf ( RSNodeBase* rNodeBase );
            unsigned int                ChildNodesSize ( bool rRecursive = false );
            RSNodes                     ChildNodes () const;
            RSNodesIterator             ChildNodesIterator() const;
            bool                        IsRootElement () const;
            bool                        IsDirty () const;
            RSNodeType                  NodeType () const;
            QMatrix4x4                  AccumlatedLocalTransform ();
            QMatrix4x4                  AccumlatedWorldTransform ();

        public slots:
            void                        SetScopeId ( const QString& rName, bool rEmit = true );
            void                        SetDirty ( bool rOnOff );
            RSError                     AddTransformation ( RSTransformationElement* rTransformationElement );
            RSError                     RemoveTransformation ( RSTransformationElement* rTransformationElement );
            RSError                     RemoveTransformation ( const QString& rScopeId );
            RSError                     RemoveTransformation ( unsigned int rIndex );
            RSError                     AddChildNode ( RSNodeBase* rNodeBase );
            RSError                     RemoveChildNode ( RSNodeBase* rNodeBase );
            RSError                     RemoveChildNode ( const QString& rId );
            RSError                     RemoveChildNode ( unsigned int rIndex );

        signals:
            void                        TransformationAdded ( RSNodeBase* rNodeBase, RSTransformationElement* rTransformationElement );
            void                        TransformationRemoved ( RSNodeBase* rNodeBase, RSTransformationElement* rTransformationELement );
            void                        NodeChildAdded ( RSNodeBase* rNodeBase, RSNodeBase* rChildNode );
            void                        NodeChildRemoved ( RSNodeBase* rNodeBase, RSNodeBase* rChildNode );
            void                        ScopeIdChanged ( RSNodeBase* rNodeBase, const QString& rScopeId );

        protected:
            RSError                     BeforeAddChildElement ( RSElement* rChild );
            bool                        AfterAddChildElement ( RSElement* rChild );
            bool                        AfterRemoveChildElement ( RSElement* rChild );
            void                        UpdateTransformations ();

        private:
            QString                     mScopeId;
            RSNodeType                  mNodeType;
            RSNodes                     mChildNodes;
            RSTransformations           mTransformations;
            RSTransformations           mRotations;
            RSTransformations           mTranslations;
            RSTransformations           mMatrices;
            RSTransformations           mScales;
            RSTransformationElement*    mSkew;
            RSTransformationElement*    mLookAt;
            QMatrix4x4                  mAccumlatedLocalTransform;
            QMatrix4x4                  mAccumlatedWorldTransform;
            bool                        mDirty;
    };

}

#endif /* RSNODEBASE_H_ */
